package com.eduagent.xwqeduagent.api.TextCorrection;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 讯飞文本纠错API客户端
 */
@Slf4j
@Component
public class TextCorrectionClient {

    private static final String API_URL = "https://api.xf-yun.com/v1/private/s9a87e3ec";
    private static final String HOST = "api.xf-yun.com";
    private static final String REQUEST_LINE = "POST /v1/private/s9a87e3ec HTTP/1.1";
    
    @Value("${xunfei.api.text-correction.appid:${xfyun.appid:}}")
    private String appId;
    
    @Value("${xunfei.api.text-correction.apikey:${xfyun.apikey:}}")
    private String apiKey;
    
    @Value("${xunfei.api.text-correction.apisecret:${xfyun.apisecret:}}")
    private String apiSecret;
    
    private final HttpClient httpClient;
    
    public TextCorrectionClient() {
        this.httpClient = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .build();
    }
    
    /**
     * 发送文本纠错请求
     * @param text 待纠错的文本内容
     * @param uid 用户ID（使用黑白名单时必传）
     * @param resId 资源ID（使用黑白名单时必传）
     * @return 纠错结果
     * @throws IOException 请求异常
     * @throws InterruptedException 请求中断异常
     */
    public TextCorrectionResult correct(String text, String uid, String resId) throws IOException, InterruptedException {
        // 检查文本长度
        if (text.length() > 2000) {
            throw new IllegalArgumentException("文本长度不能超过2000个字符");
        }
        
        // 生成鉴权参数
        String date = getGMTDate();
        String authUrl = getAuthUrl(date);
        
        // 构建请求体
        String requestBody = buildRequestBody(text, uid, resId);
        
        // 发送HTTP请求
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(authUrl))
                .header("Content-Type", "application/json")
                .header("Date", date)
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();
        
        // 发送请求并获取响应
        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        
        // 检查响应状态码
        int statusCode = response.statusCode();
        if (statusCode != 200) {
            log.error("文本纠错请求失败，状态码：{}，响应：{}", statusCode, response.body());
            throw new IOException("文本纠错请求失败，状态码：" + statusCode);
        }
        
        // 解析响应结果
        return parseResponse(response.body());
    }
    
    /**
     * 构建请求体
     */
    private String buildRequestBody(String text, String uid, String resId) {
        JSONObject json = new JSONObject();
        
        // header部分
        JSONObject header = new JSONObject();
        header.put("app_id", appId);
        header.put("status", 3);
        if (uid != null && !uid.isEmpty()) {
            header.put("uid", uid);
        }
        json.put("header", header);
        
        // parameter部分
        JSONObject parameter = new JSONObject();
        JSONObject s9a87e3ec = new JSONObject();
        if (resId != null && !resId.isEmpty()) {
            s9a87e3ec.put("res_id", resId);
        }
        
        JSONObject result = new JSONObject();
        result.put("encoding", "utf8");
        result.put("compress", "raw");
        result.put("format", "json");
        s9a87e3ec.put("result", result);
        parameter.put("s9a87e3ec", s9a87e3ec);
        json.put("parameter", parameter);
        
        // payload部分
        JSONObject payload = new JSONObject();
        JSONObject input = new JSONObject();
        input.put("encoding", "utf8");
        input.put("compress", "raw");
        input.put("format", "json");
        input.put("status", 3);
        input.put("text", Base64.encodeBase64String(text.getBytes(StandardCharsets.UTF_8)));
        payload.put("input", input);
        json.put("payload", payload);
        
        return json.toJSONString();
    }
    
    /**
     * 解析响应结果
     */
    private TextCorrectionResult parseResponse(String responseBody) {
        JSONObject responseJson = JSON.parseObject(responseBody);
        
        // 检查响应码
        JSONObject header = responseJson.getJSONObject("header");
        int code = header.getIntValue("code");
        if (code != 0) {
            String message = header.getString("message");
            log.error("文本纠错服务调用失败，错误码：{}，错误信息：{}", code, message);
            throw new RuntimeException("文本纠错服务调用失败，错误码：" + code + "，错误信息：" + message);
        }
        
        // 获取结果文本
        JSONObject payload = responseJson.getJSONObject("payload");
        JSONObject result = payload.getJSONObject("result");
        String resultText = result.getString("text");
        
        // Base64解码结果
        String decodedText = new String(Base64.decodeBase64(resultText), StandardCharsets.UTF_8);
        log.debug("文本纠错原始结果：{}", decodedText);
        
        // 解析纠错结果
        TextCorrectionResult correctionResult = JSON.parseObject(decodedText, TextCorrectionResult.class);
        
        return correctionResult;
    }
    
    /**
     * 获取GMT格式的日期字符串
     */
    private String getGMTDate() {
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        return format.format(new Date());
    }
    
    /**
     * 生成鉴权URL
     */
    private String getAuthUrl(String date) {
        try {
            // 构建鉴权原始字符串
            String signatureOrigin = "host: " + HOST + "\n" +
                    "date: " + date + "\n" +
                    REQUEST_LINE;
            
            // 使用HMAC-SHA256算法生成签名
            Mac hmacSha256 = Mac.getInstance("HmacSHA256");
            hmacSha256.init(new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            byte[] signatureSha = hmacSha256.doFinal(signatureOrigin.getBytes(StandardCharsets.UTF_8));
            String signature = Base64.encodeBase64String(signatureSha);
            
            // 构建authorization参数原始字符串
            String authorizationOrigin = "api_key=\"" + apiKey + "\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"" + signature + "\"";
            
            // Base64编码
            String authorization = Base64.encodeBase64String(authorizationOrigin.getBytes(StandardCharsets.UTF_8));
            
            // URL编码date参数
            String encodedDate = URLEncoder.encode(date, StandardCharsets.UTF_8.toString());
            
            // 拼接最终URL
            return API_URL + "?authorization=" + authorization +
                    "&host=" + HOST +
                    "&date=" + encodedDate;
            
        } catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) {
            log.error("生成鉴权URL失败", e);
            throw new RuntimeException("生成鉴权URL失败", e);
        }
    }
} 